既存のPythonコンソールアプリをDockerに移行する
はじめに
Pythonで作成したコンソールアプリをPythonがインストールされていないPCでも引き続き開発できるようにするために、Docker環境に移行したいと思います。
環境
- アプリを作成した環境
- Windows 10
- Python 3.12.1
- PythonのないPCの環境
- Windows 11
- Dockerインストール済み
移行するアプリ
今回はシンプルなPythonコンソールアプリを移行します。内容はtiktokenというライブラリを使ってOpenAIのトークン数を計算するというものです。
import tiktoken
prompt = """You are an American English conversation instructor whose native language is English.
Please provide feedback on English diaries written by students.
"""
def num_tokens_from_string(string: str, encoding_name: str) -> int:
"""Returns the number of tokens in a text string."""
encoding = tiktoken.encoding_for_model(encoding_name)
num_tokens = len(encoding.encode(string))
return num_tokens
if __name__ == "__main__":
tokens = num_tokens_from_string(prompt, "gpt-4")
print(f"Number of tokens: {tokens}")
フォルダ構成は以下の通りです。
┌─ .venv/
├─ .gitignore
├─ main_original.py
└─ requirements.txt
Dockerfileの作成
まずはDockerfileを作成します。DockerfileはDockerイメージをビルドするための手順を定義したファイルです。
ベースイメージとは、Dockerイメージの元となる環境で、OSや特定の言語のランタイム、フレームワークなどが含まれています。ベースイメージは公式から提供されているイメージを使うこともできますが、独自で環境をカスタマイズしたイメージを使うこともできます。今回はPython公式のイメージをベースとして使用します。このイメージにはPythonのランタイムや標準ライブラリが含まれているため、Pythonアプリを簡単に構築することができます。
WORKDIR
でコンテナ内の作業ディレクトリを設定します。この設定により、その後のすべてのコマンドが指定されたディレクトリ内で実行されます。
# ベースイメージ
FROM python:3.12
WORKDIR /app
# requirements.txtを元にパッケージをインストール
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY main_original.py .
CMD ["python", "main_original.py"]
Dockerfileを追加後のフォルダ構成です。
┌─ .venv/
├─ .gitignore
├─ Dockerfile
├─ main_original.py
└─ requirements.txt
以下のコマンドでビルドを行います。-t
オプションは、Dockerイメージにタグ(名前)をつけるためのものです。タグをつけることで、Dockerイメージの管理がしやすくなります。
コマンドの最後の .
は、現在の作業ディレクトリを示しています。作業ディレクトリにあるすべてのファイルとサブディレクトリがビルドプロセス中にDockerデーモンによって参照されるようになります。
参考:https://docs.docker.com/build/concepts/context/
docker build -t calc_token .
Rancher Desktopなどのコンテナ管理ツールで確認すると、Dockerイメージが追加されています。
作成したDockerイメージからコンテナを作成して実行します。
-it
オプションは-i
オプションと-t
オプションの組み合わせです。
-i
オプションはインタラクティブモードであり、シェルやプログラムと対話できるようになります。
-t
オプションはコマンド入力や実行といった端末機能を使えるようになります。
この2つを組み合わせることにより、インタラクティブなシェルを使ってコンテナを操作できる環境が実現できます。
ただしコンテナが実行するコマンドpython main_original.py
が終了するとコンテナ自体も終了するので、今回は対話できるような画面にはなりません。
docker run -it calc_token
コマンドを実行するとコンソールにトークン数が表示され、アプリが実行されたことがわかります。
複数のファイルを含める
これでコンテナ起動と同時にmain_original.py
ファイルを実行させることができましたが、特定のファイルを実行するのではなく、python
コマンドでファイルを指定して実行するようにしたいと思います。
2つ目のpyファイルを作成します。
print("This is a second file.")
second_file.py
を追加後のフォルダ構成です。
┌─ .venv/
├─ .gitignore
├─ Dockerfile
├─ main_original.py
├─ requirements.txt
└─ second_file.py
Dockerfileを以下のように修正します。
main_original.py
のみコピーしていたのを全ファイルコピーするようにし、最後にpython
コマンドでmain_original.py
を実行していた行を削除しました。
# ベースイメージ
FROM python:3.12
WORKDIR /app
# requirements.txtを元にパッケージをインストール
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
再度ビルドします。
docker build -t calc_token .
作成したDockerイメージからコンテナを作成して実行します。このときDocker内のbashを起動します。
docker run -it calc_token /bin/bash
ファイルを選択して実行します。
python second_file.py
実行できました。
次にPython環境のないPCで動作確認をするため、ここまでをGitHub等にコミットしておきます。
Python環境のないPCで実行
PythonがインストールされていないPCで、GitHubからリポジトリをクローンします。
上記と同じコマンドでビルドします。イメージ名は少し変えてみました。
docker build -t python_scripts .
ビルドできました。
続いてコンテナを起動します。
初めは上記と同じコマンドを実行しました。
docker run -it python_scripts /bin/bash
このコマンドを実行すると、新環境では以下のようなエラーになりました。
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "C:/Program Files/Git/usr/bin/sh": stat C:/Program Files/Git/usr/bin/sh: no such file or directory: unknown.
色々試行錯誤した結果、以下のコマンドなら動くことがわかりました。(なぜ/bin/bashで動かないのかまで調べられていません)
docker run -it python_scripts bash
何はともあれ、無事にPythonアプリを実行することができました。
おわりに
シンプルなアプリをDockerに移行してみました。引き続きWebアプリやマイクロサービスもDocker化していきたいと思います。
この記事がどなたかの参考になれば幸いです。